Add code to make handling domain poweroff/reboot symmetrical between
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 6 Apr 2006 14:24:00 +0000 (15:24 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 6 Apr 2006 14:24:00 +0000 (15:24 +0100)
paravirtualized and fully virtualized.  This approach uses the new
sched_op to handle other domains than the current domain.  The new
code, SCHEDOP_remote_shutdown, is very much like SCHEDOP_shutdown, but
is called with the id of the domain which is to be shut down. This
allows fully virtualized shutdown and para-virtualized shutdown to be
identical from that point forward.

A paravirtualized domain uses sched_op to shut down and set the reason
code. This will send a VIRQ_DOM_EXC, which can be handled in dom0 by
control software.  In some ways, this resembles SIGCHILD/waitpid, and
is a reasonable model.

The fully virtualized case has qemu invoke xm directly. This is a
different path than paravirtualized. It also removes decision and
policy making choices from the rest of the control software and places
it within qemu. When any dom0 logic eventually gets a VIRQ_DOM_EXC,
the information about the domain is gone having been destroyed by xm.

A libxenctrl wrapper, xc_shutdown_domain has been added and qemu now
calls it.

As a freebie, #if 0 some very verbose logging code in qemu.  Totally
unrelated, but as long as I was there...

Signed-off-by: Ben Thomas <ben@virtualiron.com>
linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
tools/ioemu/target-i386-dm/helper2.c
tools/ioemu/vl.c
tools/libxc/xc_domain.c
tools/libxc/xenctrl.h
xen/common/schedule.c
xen/include/public/sched.h

index 52364f9aeb6bb4079f7b72ff20a3a5d04eec4009..e572fa7c795de0263ebe42fb2a539cb12e6df9dc 100644 (file)
@@ -277,6 +277,7 @@ static int __init privcmd_init(void)
        set_bit(__HYPERVISOR_mmu_update,       hypercall_permission_map);
        set_bit(__HYPERVISOR_mmuext_op,        hypercall_permission_map);
        set_bit(__HYPERVISOR_xen_version,      hypercall_permission_map);
+       set_bit(__HYPERVISOR_sched_op,         hypercall_permission_map);
 
        privcmd_intf = create_xen_proc_entry("privcmd", 0400);
        if (privcmd_intf != NULL)
index af4a8e8d8bbe311263876e47212539468cdf2144..a596c6edabb8b45523433ce6aa1866b98c8c7928 100644 (file)
@@ -409,12 +409,20 @@ int xc_handle;
 void
 destroy_hvm_domain(void)
 {
-    extern FILE* logfile;
-    char destroy_cmd[32];
-
-    sprintf(destroy_cmd, "xm destroy %d", domid);
-    if (system(destroy_cmd) == -1)
-        fprintf(logfile, "%s failed.!\n", destroy_cmd);
+   int xcHandle;
+   int sts;
+   xcHandle = xc_interface_open();
+   if (xcHandle < 0)
+     fprintf(logfile, "Cannot acquire xenctrl handle\n");
+   else {
+     sts = xc_domain_shutdown(xcHandle, domid, SHUTDOWN_poweroff);
+     if (sts != 0)
+       fprintf(logfile, "? xc_domain_shutdown failed to issue poweroff, sts %d, errno %d\n", sts, errno);
+     else
+       fprintf(logfile, "Issued domain %d poweroff\n", domid);
+     xc_interface_close(xcHandle);
+   }
 }
 
 fd_set wakeup_rfds;
@@ -480,13 +488,24 @@ int main_loop(void)
 
 static void qemu_hvm_reset(void *unused)
 {
-    char cmd[64];
-
-    /* pause domain first, to avoid repeated reboot request*/
-    xc_domain_pause(xc_handle, domid);
-
-    sprintf(cmd, "xm shutdown -R %d", domid);
-    system(cmd);
+   int xcHandle;
+   int sts;
+
+   /* pause domain first, to avoid repeated reboot request*/
+   xc_domain_pause(xc_handle, domid);
+
+   xcHandle = xc_interface_open();
+   if (xcHandle < 0)
+     fprintf(logfile, "Cannot acquire xenctrl handle\n");
+   else {
+     sts = xc_domain_shutdown(xcHandle, domid, SHUTDOWN_reboot);
+     if (sts != 0)
+       fprintf(logfile, "? xc_domain_shutdown failed to issue reboot, sts %d\n", sts);
+     else
+       fprintf(logfile, "Issued domain %d reboot\n", domid);
+     xc_interface_close(xcHandle);
+   }
 }
 
 CPUState * cpu_init()
index 6586f77deb9019bd6d2ba53c48038dfab787c6d0..da009dd11bfe5c4c8c6400545cae5f99b6785004 100644 (file)
@@ -2556,8 +2556,10 @@ static int set_mm_mapping(int xc_handle,
         return -1;
     }
 
+#if 0 /* Generates lots of log file output - turn on for debugging */
     for (i = 0; i < nr_pages; i++)
         fprintf(stderr, "set_map result i %x result %lx\n", i, extent_start[i]);
+#endif
 
     return 0;
 }
index ea2ca76d1b0371b827177d2ecde2742e8d1402c3..3b9abd11f8d363b5b2e10e898c67d5c5907ad334 100644 (file)
@@ -58,6 +58,35 @@ int xc_domain_destroy(int xc_handle,
     return do_dom0_op(xc_handle, &op);
 }
 
+int xc_domain_shutdown(int xc_handle,
+                       uint32_t domid,
+                       int reason)
+{
+    int ret = -1;
+    sched_remote_shutdown_t arg;
+    DECLARE_HYPERCALL;
+
+    hypercall.op     = __HYPERVISOR_sched_op;
+    hypercall.arg[0] = (unsigned long)SCHEDOP_remote_shutdown;
+    hypercall.arg[1] = (unsigned long)&arg;
+    arg.domain_id = domid;
+    arg.reason = reason;
+
+    if ( mlock(&arg, sizeof(arg)) != 0 )
+    {
+        PERROR("Could not lock memory for Xen hypercall");
+        goto out1;
+    }
+
+    ret = do_xen_hypercall(xc_handle, &hypercall);
+
+    safe_munlock(&arg, sizeof(arg));
+
+ out1:
+    return ret;
+}
+
+
 int xc_vcpu_setaffinity(int xc_handle,
                         uint32_t domid, 
                         int vcpu,
index fce21b7334e3cec3b67c3422fe80f4c060fd1346..3bc124d77d4c10795f25a8c7237975d1672f91c3 100644 (file)
@@ -206,6 +206,21 @@ int xc_domain_unpause(int xc_handle,
 int xc_domain_destroy(int xc_handle, 
                       uint32_t domid);
 
+/**
+ * This function will shutdown a domain. This is intended for use in
+ * fully-virtualized domains where this operation is analogous to the
+ * sched_op operations in a paravirtualized domain. The caller is
+ * expected to give the reason for the shutdown.
+ *
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm domid the domain id to destroy
+ * @parm reason is the reason (SHUTDOWN_xxx) for the shutdown
+ * @return 0 on success, -1 on failure
+ */
+int xc_domain_shutdown(int xc_handle, 
+                       uint32_t domid,
+                       int reason);
+
 int xc_vcpu_setaffinity(int xc_handle,
                         uint32_t domid,
                         int vcpu,
index 0b1644ea5a1004c311f033b8b36f400e190bf7ad..5fe6cb4304dcccdb6fa1c3390e3acff6b5793023 100644 (file)
@@ -413,6 +413,30 @@ long do_sched_op(int cmd, GUEST_HANDLE(void) arg)
         break;
     }
 
+    case SCHEDOP_remote_shutdown:
+    {
+        struct domain *d;
+        struct sched_remote_shutdown sched_remote_shutdown;
+
+        if ( !IS_PRIV(current->domain) )
+            return -EPERM;
+
+        ret = -EFAULT;
+        if ( copy_from_guest(&sched_remote_shutdown, arg, 1) )
+            break;
+
+        ret = -ESRCH;
+        d = find_domain_by_id(sched_remote_shutdown.domain_id);
+        if ( d == NULL )
+            break;
+
+        domain_shutdown(d, (u8)sched_remote_shutdown.reason);
+        put_domain(d);
+        ret = 0;
+
+        break;
+    }
+
     default:
         ret = -ENOSYS;
     }
index 28e86c0d7673213eb820a113da476fce8761161a..27f321e08042e26ac7d1c5a60c724499f555c457 100644 (file)
@@ -64,6 +64,19 @@ typedef struct sched_poll {
 } sched_poll_t;
 DEFINE_GUEST_HANDLE(sched_poll_t);
 
+/*
+ * Declare a shutdown for another domain. The main use of this function is
+ * in interpreting shutdown requests and reasons for fully-virtualized
+ * domains.  A para-virtualized domain may use SCHEDOP_shutdown directly.
+ * @arg == pointer to sched_remote_shutdown structure.
+ */
+#define SCHEDOP_remote_shutdown        4
+typedef struct sched_remote_shutdown {
+    domid_t domain_id;         /* Remote domain ID */
+    unsigned int reason;       /* SHUTDOWN_xxx reason */
+} sched_remote_shutdown_t;
+DEFINE_GUEST_HANDLE(sched_remote_shutdown_t);
+
 /*
  * Reason codes for SCHEDOP_shutdown. These may be interpreted by control
  * software to determine the appropriate action. For the most part, Xen does